package com.m3u8;

import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Build;
import android.os.HandlerThread;
import android.os.Looper;
import android.widget.Toast;

import com.m3u8.db.DbAction;
import com.m3u8.db.DownloadM3u8DB;
import com.m3u8.db.M3u8DbCallback;
import com.m3u8.db.model.M3u8Model;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * 下载控制器，并从中和数据库查询结合
 */
public class Downloader {

    private static Downloader instance;
    private HandlerThread mDownHandlerThread;

    private static Downloader getInstance() {
        if (instance == null) {
            synchronized (Downloader.class) {
                if (instance == null) {
                    instance = new Downloader();
                }
            }
        }
        return instance;
    }

    private Downloader() {
        mDownHandlerThread = new HandlerThread("download-m3u8");
        mDownHandlerThread.start();
    }

    /**
     * 获取Downloader的整体looper
     *
     * @return
     */
    static Looper getLooper() {
        return getInstance().mDownHandlerThread.getLooper();
    }

    public static void startDownload(Context context, String url) {
        getInstance().start(context, url, "", "", "", null);
    }

    public static void startDownload(Context context, String url, String localPath, String basePath) {
        getInstance().start(context, url, localPath, basePath, "", null);
    }

    public static void startDownload(Context context, String url, String localPath, String basePath, String name) {
        getInstance().start(context, url, localPath, basePath, name, null);
    }

    public static void startDownload(Context context, String url, String localPath, String basePath, String name, ServiceConnection serviceConnection) {
        getInstance().start(context, url, localPath, basePath, name, serviceConnection);
    }

    /**
     * 刷新列表
     *
     * @param context
     */
    public static synchronized void refreshDownload(Context context) {
        getInstance().refresh(context);
    }

    public static synchronized void pauseDownload(Context context, String url) {
        getInstance().pause(context, url);
    }

    /**
     * 开始全部
     */
    public static synchronized void startAllDownload(Context context) {
        getInstance().startAll(context);
    }


    /**
     * 暂停全部
     */
    public static synchronized void pauseAllDownload(Context context) {
        getInstance().pauseAll(context);
    }

    /**
     * 销毁事件
     */
    public static void release() {
        getInstance().releaseDL();
    }

    private void releaseDL() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
            mDownHandlerThread.quitSafely();
        } else {
            mDownHandlerThread.quit();
        }
        mDownHandlerThread = null;
        instance = null;
    }

    /**
     * 开启
     *
     * @param context
     * @param url
     * @param localPath
     * @param name
     * @param serviceConnection
     */
    private synchronized void start(Context context, final String url, final String localPath, final String basePath, final String name, final ServiceConnection serviceConnection) {
        final Context application = context.getApplicationContext();
        // TODO 需要优化，仿Rxjava的响应式优化
        DataBaser.runDb(new DbAction() {
            @Override
            public Object action() {
                return DownloadM3u8DB.getInstance(application).m3u8Dao().queryAllByUrl(url);
            }
        }, new M3u8DbCallback(context, serviceConnection) {
            @Override
            public Object back(Object result) {
                List<M3u8Model> m3u8Models = (List<M3u8Model>) result;
                Context mContext = contextWeakReference.get();
                if (mContext == null) {
                    return true;
                }
                if (m3u8Models.isEmpty()) { // 没有下载记录
                    Intent intent = new Intent(mContext, DownloadTsService.class);
                    RequestInfo info = new RequestInfo.Builder().setM3u8url(url).setName(name).setM3u8Path(localPath).setBasePath(basePath).build();
                    info.requestStats = DownloadConstats.Request.START;
                    intent.putExtra(DownloadConstats.KEY.SERVICE_INTENT_EXTRA, info);
                    if (serviceConnectionWeakReference == null || serviceConnectionWeakReference.get() == null) { // 启动服务不返回
                        mContext.startService(intent);
                    } else { // IPC 通信
                        mContext.startService(intent); //重点:造成长期service，使unBindService不关闭service
                        mContext.bindService(intent, serviceConnectionWeakReference.get(), Context.BIND_AUTO_CREATE);
                    }
                } else {
                    final M3u8Model m3u8Model = m3u8Models.get(0);
                    if (m3u8Model.getState() != DownloadConstats.STATE.STATE_M3U8_SUCCESS) { // 下载成功外所有状态可以进入
                        Intent intent = new Intent(mContext, DownloadTsService.class);
                        RequestInfo info = new RequestInfo.Builder().setM3u8url(url).setName(name).setM3u8Path(localPath).setBasePath(basePath).build();
                        info.requestStats = DownloadConstats.Request.RESUME;
                        info.m3u8Id = m3u8Model.getId();
                        info.state = m3u8Model.getState();
                        info.process = m3u8Model.getHasDownSize() * 100 / m3u8Model.getTsSize();
                        intent.putExtra(DownloadConstats.KEY.SERVICE_INTENT_EXTRA, info);
                        if (serviceConnectionWeakReference == null || serviceConnectionWeakReference.get() == null) { // 启动服务不返回
                            mContext.startService(intent);
                        } else { // IPC 通信
                            mContext.startService(intent); //重点:造成长期service，使unBindService不关闭service
                            mContext.bindService(intent, serviceConnectionWeakReference.get(), Context.BIND_AUTO_CREATE);
                        }
                    } else { // 有下载记录
                        String m3u8Path = m3u8Model.getLocalPath();
                        final long m3u8Id = m3u8Model.getId();
                        File file = new File(m3u8Path);
                        if (!file.exists()) { // 文件不存在，删除数据库数据并回调重新走一次
                            DataBaser.runDb(new DbAction() {
                                @Override
                                public Object action() {
                                    return DownloadM3u8DB.getInstance(application).m3u8Dao().delete(m3u8Id);
                                }
                            });
                            start(mContext, url, localPath, basePath, name, serviceConnection);
                        } else {
                            Toast.makeText(mContext, "已经下载完成", Toast.LENGTH_LONG).show();
                        }
                    }
                }
                return true;
            }
        });
    }

    /**
     * 刷新
     *
     * @param context
     */
    private synchronized void refresh(Context context) {
        final Context application = context.getApplicationContext();
        DataBaser.runDb(new DbAction() {
            @Override
            public Object action() {
                return DownloadM3u8DB.getInstance(application).m3u8Dao().getM3u8NotSuccess(DownloadConstats.STATE.STATE_M3U8_SUCCESS);
            }
        }, new M3u8DbCallback(context) {
            @Override
            public Object back(Object result) {
                List<M3u8Model> m3u8Models = (List<M3u8Model>) result;
                Context mContext = contextWeakReference.get();
                if (!m3u8Models.isEmpty() && mContext != null) {
                    ArrayList<RequestInfo> requestInfos = new ArrayList<>();
                    for (M3u8Model m3u8Model : m3u8Models) {
                        RequestInfo requestInfo = new RequestInfo.Builder()
                                .setM3u8url(m3u8Model.getUrl())
                                .setM3u8Path(m3u8Model.getLocalPath())
                                .build();
                        requestInfo.m3u8Id = m3u8Model.getId();
                        requestInfo.state = m3u8Model.getState();
                        requestInfo.process = m3u8Model.getHasDownSize() * 100 / m3u8Model.getTsSize();
                        requestInfo.requestStats = DownloadConstats.Request.REFRESH;
                        requestInfos.add(requestInfo);
                    }
                    Intent intent = new Intent(mContext, DownloadTsService.class);
                    intent.putParcelableArrayListExtra(DownloadConstats.KEY.SERVICE_INTENT_EXTRA_LIST, requestInfos);
                    mContext.startService(intent);
                }
                return true;
            }
        });
    }

    /**
     * 暂停
     *
     * @param context
     * @param url
     */
    private synchronized void pause(Context context, final String url) {
        final Context application = context.getApplicationContext();
        DataBaser.runDb(new DbAction() {
            @Override
            public Object action() {
                return DownloadM3u8DB.getInstance(application).m3u8Dao().queryAllByUrl(url);
            }
        }, new M3u8DbCallback(context) {
            @Override
            public Object back(Object result) {
                List<M3u8Model> m3u8Models = (List<M3u8Model>) result;
                Context mContext = contextWeakReference.get();
                if (!m3u8Models.isEmpty() && mContext != null) {
                    M3u8Model m3u8Model = m3u8Models.get(0);
                    if (m3u8Model.getState() != DownloadConstats.STATE.STATE_M3U8_PAUSE
                            && m3u8Model.getState() != DownloadConstats.STATE.STATE_M3U8_SUCCESS) {
                        Intent intent = new Intent(mContext, DownloadTsService.class);
                        RequestInfo info = new RequestInfo.Builder().setM3u8url(url).build();
                        info.requestStats = DownloadConstats.Request.PAUSE;
                        info.state = m3u8Model.getState();
                        info.m3u8Id = m3u8Model.getId();
                        info.process = m3u8Model.getHasDownSize() * 100 / m3u8Model.getTsSize();
                        intent.putExtra(DownloadConstats.KEY.SERVICE_INTENT_EXTRA, info);
                        mContext.startService(intent);
                    }
                }
                return true;
            }
        });
    }

    private synchronized void startAll(Context context) {
        final Context application = context.getApplicationContext();
        DataBaser.runDb(new DbAction() {
            @Override
            public Object action() {
                return DownloadM3u8DB.getInstance(application).m3u8Dao().getM3u8NotSuccess(DownloadConstats.STATE.STATE_M3U8_SUCCESS);
            }
        }, new M3u8DbCallback(context) {
            @Override
            public Object back(Object result) {
                List<M3u8Model> m3u8Models = (List<M3u8Model>) result;
                Context mContext = contextWeakReference.get();
                if (!m3u8Models.isEmpty() && mContext != null) {
                    for (M3u8Model m3u8Model : m3u8Models) {
                        if (m3u8Model.getState() == DownloadConstats.STATE.STATE_M3U8_PAUSE) {
                            Intent intent = new Intent(mContext, DownloadTsService.class);
                            RequestInfo info = new RequestInfo.Builder().setM3u8url(m3u8Model.getUrl()).build();
                            info.requestStats = DownloadConstats.Request.RESUME;
                            info.state = m3u8Model.getState();
                            info.m3u8Id = m3u8Model.getId();
                            info.process = m3u8Model.getHasDownSize() * 100 / m3u8Model.getTsSize();
                            intent.putExtra(DownloadConstats.KEY.SERVICE_INTENT_EXTRA, info);
                            mContext.startService(intent);
                        }
                    }
                }
                return true;
            }
        });
    }

    private synchronized void pauseAll(Context context) {
        final Context application = context.getApplicationContext();
        DataBaser.runDb(new DbAction() {
            @Override
            public Object action() {
                return DownloadM3u8DB.getInstance(application).m3u8Dao().getM3u8NotSuccess(DownloadConstats.STATE.STATE_M3U8_SUCCESS);
            }
        }, new M3u8DbCallback(context) {
            @Override
            public Object back(Object result) {
                List<M3u8Model> m3u8Models = (List<M3u8Model>) result;
                Context mContext = contextWeakReference.get();
                if (!m3u8Models.isEmpty() && mContext != null) {
                    for (M3u8Model m3u8Model : m3u8Models) {
                        if (m3u8Model.getState() != DownloadConstats.STATE.STATE_M3U8_PAUSE
                                && m3u8Model.getState() != DownloadConstats.STATE.STATE_M3U8_SUCCESS) {
                            Intent intent = new Intent(mContext, DownloadTsService.class);
                            RequestInfo info = new RequestInfo.Builder().setM3u8url(m3u8Model.getUrl()).build();
                            info.requestStats = DownloadConstats.Request.PAUSE;
                            info.state = m3u8Model.getState();
                            info.m3u8Id = m3u8Model.getId();
                            info.process = m3u8Model.getHasDownSize() * 100 / m3u8Model.getTsSize();
                            intent.putExtra(DownloadConstats.KEY.SERVICE_INTENT_EXTRA, info);
                            mContext.startService(intent);
                        }
                    }
                }
                return true;
            }
        });
    }
}
